//************************************************************************************
// Copyright (C) 2003-2004 Alpha Imaging Technology Corp.
// This file is confidential. All rights reserved.
// Description : AIT810 firmware source code
//************************************************************************************
//#define exUSBSTD
#include "includes_fw.h"
#include "lib_retina.h"
#include "mmpf_usbvend.h"
#include "mmpf_usbextrn.h"
#include "mmpf_usbdescr.h"

#include "mmp_reg_gbl.h"
#include "mmpf_audio_ctl.h"
#include "mmpf_usbuac.h"

#include "mmpf_pll.h"

#if (SUPPORT_MTP_FUNC==1)
#include "mmpf_usbmtp.h"
#endif

#include "mmps_3gprecd.h"
#include "mmpf_usbpccam.h"
#include "mmpf_usbuvc.h"
#include "mmpf_system.h"
#include "mmpd_system.h"
#include "pcam_usb.h"
#include "pcam_handler.h"
#include "mmpf_msg.h"
#include "mmp_reg_usb.h"
#include "customer.h"
#include "mmpf_sensor.h"

/** @addtogroup MMPF_USB
@{
*/

#if SUPPORT_UVC_FUNC == 0
extern USB_REQUEST_PAYLOAD UsbRequestPayload;
extern MMP_USHORT  gsUsbEp0Status;
extern MMP_USHORT  gsUsbRxEpStatus[MAX_RX_ENDPOINT_NUM];
extern MMP_USHORT  gsUsbTxEpStatus[MAX_TX_ENDPOINT_NUM];
extern MMP_ULONG   glUsbUpdateDeviceAddr;
extern MMP_USHORT  gsUsbDeviceStatus;
extern MMP_USHORT  gsUsbInterfaceStatus[MAX_INTERFACE_NUM];
extern MMP_ULONG   glUsbCurrentConfig;
extern MMP_ULONG   glUsbCurrentInterface;
extern MMP_ULONG   glUsbCtlState;
extern MMP_ULONG   glUsbCtlTxCnt;
#endif
#if USE_SIMPLIFIED_DESC == 0
extern   MMP_UBYTE  USBDescBufAddr[];
extern USB_DESCRIPTOR      UsbDescriptorInfo;
#endif
extern MMP_ULONG   glTestModeFeature;

#if defined(USB_FW)||(USB_EN)

#pragma O2




#if (SUPPORT_UVC_FUNC==1)
extern MMP_UBYTE UsbRequestPayload_bRequest;
extern MMP_USHORT UsbRequestPayload_wValue;
extern MMP_USHORT UsbRequestPayload_wIndex;
extern MMP_USHORT UsbRequestPayload_wLength;
extern MMP_UBYTE  gbUsbHighSpeed;
extern   MMP_USHORT USBEP0TxCnt;
extern   MMP_UBYTE  USBInPhase;
extern   MMP_USHORT USBFrameNum;
extern   MMP_UBYTE  USBConfig;
extern   MMP_UBYTE  USBInterface;
extern   MMP_UBYTE  USBRequestType;
extern   MMP_UBYTE  USBDevice; 
extern   MMP_UBYTE  USBCmd;
extern   MMP_UBYTE  gbEP0NotEnd;
extern   MMP_UBYTE  USBOutPhase;  
extern   MMP_USHORT USBConfigDescLen;
#if SUPPORT_HID_FUNC
extern   MMP_USHORT USBReportDescLen;
#endif
extern   MMP_UBYTE  gbUvcCommitted;
extern   MMP_USHORT USBConfig1Len;
extern   MMP_UBYTE  USBAlterSetting;

#if(CUSTOMER == ASU)||(CUSTOMER == IPC)||(CUSTOMER == QDR) || (CUSTOMER == ANW)// prevent too long time waiting on Win8
MMP_BOOL  gbOSWin8Preview;
#endif
MMP_USHORT  EP0TXOffset;
static MMP_UBYTE gbUsbOtherSpeed;

#if SUPPORT_WHQL_TEST
extern int AlternateSamplingRate;
#endif

extern MMP_UBYTE gbSwitchSensor;

extern MMP_UBYTE  gbCurrentSensor;
//*****************************************************************
// function : send_getstatus_data
// input    : none
// output   : none
//*****************************************************************
void send_getstatus_data(void)
{
    USBInPhase = GET_STATUS_CMD;
    USBEP0TxCnt = 0x02;  
    //    USBEP0TxAddr = USBEP0TxBufAddr;  
    usb_ep0_in();
}

//*****************************************************************
// function : std_setup_getstatus
// input    : none
// output   : none
//*****************************************************************
void std_setup_getstatus(void)
{
	AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;
    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
    if(USBRequestType == 0) {
        pUSB_CTL->USB_FIFO_EP[0x0].FIFO_W = USBDevice;
        send_getstatus_data();
    } else if(USBRequestType == 0x01) {
        pUSB_CTL->USB_FIFO_EP[0x0].FIFO_W = USBInterface;
        send_getstatus_data();
    } else if(USBRequestType == 0x02) {
        pUSB_CTL->USB_FIFO_EP[0x0].FIFO_W = USBEndpoint;
        send_getstatus_data();
    } else {
        usb_error();
    }
}

//*****************************************************************
// function : std_in_getstatus
// input    : none
// output   : none
//*****************************************************************
void std_in_getstatus(void)
{
    USBOutPhase = GET_STATUS_CMD;
    usb_ep0_null_out();
}

#if 0
//*****************************************************************
// function : std_out_getstatus
// input    : none
// output   : none
//*****************************************************************
void std_out_getstatus(void)
{
}
#endif
//*****************************************************************
// function : send_clrfeature_data
// input    : none
// output   : none
//*****************************************************************
void send_clrfeature_data(void)
{
    USBInPhase = CLEAR_FEATURE_CMD;
    usb_ep0_null_in();
}

//*****************************************************************
// function : std_setup_clearfeature
// input    : none
// output   : none
//*****************************************************************
void std_setup_clearfeature(void)
{
    MMP_UBYTE tmp;

    tmp = UsbRequestPayload_wIndex;
    //UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
    if(USBRequestType == 0) {
        if((UsbRequestPayload_wValue & 0xFF) != 2) {
            usb_error();
        } else {
            USBDevice &= 0xFD;
            send_clrfeature_data();
        }
    } else if(USBRequestType == 0x01) {
        //           if( ((UsbRequestPayload_wIndex&0xFF)!= 0) && ((UsbRequestPayload_wIndex&0xFF)!= 1) ) {
        usb_error();
        //         }
        //      USBInterface = 0;
        //        send_clrfeature_data();
    } else if(USBRequestType == 0x02) {
        USBEndpoint &= 0xFE;
        #if USE_COMMON_CLEAR_FUNC
        if((tmp >= 0x81) && (tmp <= 0x83))
        {
            clear_ep_sequence(tmp - 0x80);
            send_clrfeature_data();
            #if USB_UVC_BULK_EP
            if ((tmp <= 0x82) && gbUvcCommitted)
            {
                usb_uvc_stop_preview();
            }
            #endif
        }
        #else
        if(tmp == 0x81) {
            clear_ep1_sequence();         
            send_clrfeature_data();
#if USB_UVC_BULK_EP			
            if(gbUvcCommitted) {
			   usb_uvc_stop_preview();
            }
#endif
        } else if(tmp == 0x82) {
            clear_ep2_sequence();
            send_clrfeature_data();
#if USB_UVC_BULK_EP			
            if(gbUvcCommitted) {
			   usb_uvc_stop_preview();
            }
#endif
        } else if(tmp == 0x83) {
            clear_ep3_sequence();
            send_clrfeature_data();
        }
        #endif
        else {
            usb_error();
        }
    } else {
        usb_error();
    }
}

//*****************************************************************
// function : std_in_clearfeature
// input    : none
// output   : none
//*****************************************************************
void std_in_clearfeature(void)
{
    USBOutPhase = CLEAR_FEATURE_CMD;
    // usb_ep0_null_out();

#if 0//(USING_MSDC == 1)
    if(USBMSDCPhase == CSW_STATE) {
        msdc_ep1_csw_phase_end();
    } else if(USBMSDCPhase == WP_STATE) {
        usb_ep2_nak();
        USBMSDCPhase = CBW_STATE;
        msdc_set_csw_header(0x01);
        msdc_tx_csw();
    } else if(USBMSDCPhase == CBW_STATE) {
        if(gbMSDCstall) {
            gbMSDCstall = 0;      
            msdc_set_csw_header(0x01);
            msdc_tx_csw();
        }
    }
#endif
}

//*****************************************************************
// function : std_out_clearfeature
// input    : none
// output   : none
//*****************************************************************
#if 0
void std_out_clearfeature(void)
{
}
#endif

//*****************************************************************
// function : send_setfeature_data
// input    : none
// output   : none
//*****************************************************************
void send_setfeature_data(void)
{
    USBInPhase = SET_FEATURE_CMD;
    usb_ep0_null_in();
}

//*****************************************************************
// function : std_setup_setfeature
// input    : none
// output   : none
//*****************************************************************
extern void StallTx(u_char endpoint);
void std_setup_setfeature(void)
{
    //UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);

    if(UsbRequestPayload_wValue == 0x02) {
        glTestModeFeature = UsbRequestPayload_wIndex;
        if((UsbRequestPayload_wIndex & 0xFF) != 0) {
            usb_error();
            return;
        }
    } else if(UsbRequestPayload_wValue == 0x00) {
        ;
    } else {
        usb_error();            
        return;
    }

    if(USBRequestType == 0) {
        if((UsbRequestPayload_wValue & 0xFF) != 2) {
            usb_error();
            return;
        }
        USBDevice |= 0x02;
        send_setfeature_data();
    } else if(USBRequestType == 0x01) {
        //           if( ((UsbRequestPayload_wIndex&0xFF)!= 0) && ((UsbRequestPayload_wIndex&0xFF)!= 1) ) {
        usb_error();
        return;
        //         }
        //           USBInterface = 0;
        //           send_setfeature_data();
    } else if(USBRequestType == 0x02) {
        //if(((UsbRequestPayload_wIndex & 0xFF) != 0x81) && ((UsbRequestPayload_wIndex & 0xFF) != 0x83)) {
        if(((UsbRequestPayload_wIndex & 0xFF) != 0x81) && ((UsbRequestPayload_wIndex & 0xFF) != 0x82) && ((UsbRequestPayload_wIndex & 0xFF) != 0x83)) {
            usb_error();
            return;
        }
        if(UsbRequestPayload_wIndex==0x83) {
           StallTx(0x03);        
        }   
        USBEndpoint |= 0x01;
        send_setfeature_data();
    } else {
        usb_error();
        return;
    }
}

//*****************************************************************
// function : std_in_setfeature
// input    : none
// output   : none
//*****************************************************************
#if 0
void std_in_setfeature(void)
{
    //    USBOutPhase = SET_FEATURE_CMD;
}

//*****************************************************************
// function : std_out_setfeature
// input    : none
// output   : none
//*****************************************************************
void std_out_setfeature(void)
{
}
#endif
//*****************************************************************
// function : std_setup_setaddress
// input    : none
// output   : none
//*****************************************************************
void std_setup_setaddress(void)
{
    USBDevAddr = UsbRequestPayload_wValue;  
    #if 0
    RTNA_DBG_Byte(0, USBDevAddr);                            
    RTNA_DBG_Str(0, "--USBDevAddr\r\n");
    #endif
    
    //    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
    USBInPhase = SET_ADDRESS_CMD;
    usb_ep0_null_in();
}

//*****************************************************************
// function : std_in_setaddress
// input    : none
// output   : none
//*****************************************************************
void std_in_setaddress(void)
{
   AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    pUSB_CTL->USB_FADDR = USBDevAddr;
}

//*****************************************************************
// function : std_out_setaddress
// input    : none
// output   : none
//*****************************************************************
#if 0
void std_out_setaddress(void)
{
}
#endif
//*****************************************************************
// function : std_setup_setdescriptor
// input    : none
// output   : none
//*****************************************************************
void std_setup_setdescriptor(void)
{
    //    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
    USBInPhase = SET_DESCRIPTOR_CMD;
    usb_ep0_null_in();
}

//*****************************************************************
// function : std_in_setdescriptor
// input    : none
// output   : none
//*****************************************************************
void std_in_setdescriptor(void)
{
    USBOutPhase = SET_DESCRIPTOR_CMD;
    // usb_ep0_null_out();  
}

//*****************************************************************
// function : std_out_setdescriptor
// input    : none
// output   : none
//*****************************************************************
#if 0
void std_out_setdescriptor(void)
{
}
#endif

//*****************************************************************
// function : std_setup_getconfiguration
// input    : none
// output   : none
//*****************************************************************
void std_setup_getconfiguration(void)
{
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = USBConfig;                           

    USBInPhase = GET_CONFIG_CMD;
    USBEP0TxCnt = 0x01;
    //    USBEP0TxAddr = USBEP0TxBufAddr;
    usb_ep0_in();
}

//*****************************************************************
// function : std_in_getconfiguration
// input    : none
// output   : none
//*****************************************************************
void std_in_getconfiguration(void)
{
    USBOutPhase = GET_CONFIG_CMD;
    usb_ep0_null_out();
}

//*****************************************************************
// function : std_out_getconfiguration
// input    : none
// output   : none
//*****************************************************************
#if 0
void std_out_getconfiguration(void)
{
}
#endif
//*****************************************************************
// function : std_setup_setconfiguration
// input    : none
// output   : none
//*****************************************************************
void std_setup_setconfiguration(void)
{
    USBConfig = UsbRequestPayload_wValue;  
    // UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);

    #if USE_COMMON_CLEAR_FUNC
    clear_ep_sequence(1);
    clear_ep_sequence(2);
    clear_ep_sequence(3);
    #else
    clear_ep1_sequence();
    clear_ep2_sequence();
    clear_ep3_sequence();
    #endif
    USBInterface = 0; 
    USBEndpoint = 0;  
    USBAlterSetting = 0; 
    USBInPhase = SET_CONFIG_CMD; 
    usb_ep0_null_in();
}

//*****************************************************************
// function : std_in_setconfiguration
// input    : none
// output   : none
//*****************************************************************
#if 0
void std_in_setconfiguration(void)
{
    //    USBOutPhase = SET_CONFIG_CMD;
}

//*****************************************************************
// function : std_out_setconfiguration
// input    : none
// output   : none
//*****************************************************************
void std_out_setconfiguration(void)
{
}
#endif
//*****************************************************************
// function : std_setup_getinterface
// input    : none
// output   : none
//*****************************************************************
void std_setup_getinterface(void)
{
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = USBAlterSetting;                           
    USBInPhase = GET_INTERFACE_CMD;
    USBEP0TxCnt = 0x01;
    //    USBEP0TxAddr = USBEP0TxBufAddr;
    usb_ep0_in();
}

//*****************************************************************
// function : std_in_getinterface
// input    : none
// output   : none
//*****************************************************************
void std_in_getinterface(void)
{
    USBOutPhase = GET_INTERFACE_CMD;
    usb_ep0_null_out();
}

//*****************************************************************
// function : std_out_getinterface
// input    : none
// output   : none
//*****************************************************************
#if 0
void std_out_getinterface(void)
{
}
#endif
//*****************************************************************
// function : std_setup_setinterface
// input    : none
// output   : none
//*****************************************************************
void std_setup_setinterface(void)
{
#if SUPPORT_WHQL_TEST
    PCAM_AUDIO_CFG *pcam_audio = pcam_get_audio_cfg();
#endif
#if BLOCK_2_UVC_INTERFACE || SUPPORT_WHQL_TEST
    MMP_BOOL IsPreviewEnable;
#endif

    USBAlterSetting = UsbRequestPayload_wValue;  
    USBInterface = UsbRequestPayload_wIndex;

    if(USBInterface == UVC_D1_CTL_IF_NO) {

    } else if(USBInterface == UVC_D1_STREAM_IF1_NO){
    
        //RTNA_DBG_Str3("VC.Cmd:");RTNA_DBG_Byte3(USBAlterSetting);RTNA_DBG_Str3("\r\n");
        
        if((gbUvcCommitted) && (USBAlterSetting/* == 0x01*/)) {
            RTNA_DBG_Str(3, "  set.v1.start\r\n");

#if BLOCK_2_UVC_INTERFACE
            //Return STALL if any interface already preview
                MMPS_3GPRECD_GetPreviewDisplay(&IsPreviewEnable);
                if(IsPreviewEnable) {
                dbg_printf(0, "! v1.start during interface %d already start\r\n", gbCurrentSensor);
                    usb_error(); //prevent host start before stop
                    return;
                }
#endif

#if SUPPORT_DUAL_DEVICE
            if(gbCurrentSensor!=0) {
				MMPF_Sensor_Set3AState(MMPF_SENSOR_3A_RESET);//sensor change! for gsSensorFunction->MMPF_Sensor_InitializeISP()==>ISP_IF_LIB_Init()
                MMPF_Sensor_SetBufferSize(0);
		}
#endif//SUPPORT_DUAL_DEVICE

			gbCurrentSensor = 0;//SensorFunction_Module0, 1M sensor
			usb_uvc_start_preview();
            #if(CUSTOMER == ASU)||(CUSTOMER == IPC)||(CUSTOMER == QDR) || (CUSTOMER == ANW)// prevent too long time waiting on Win8, return ACK after sensor init
			gbOSWin8Preview = MMP_TRUE;
			return;			
			#endif
        } else if((gbUvcCommitted) && (USBAlterSetting == 0x00)) {
            
            RTNA_DBG_Str(3, "  set.v1.stop\r\n");
            
#if BLOCK_2_UVC_INTERFACE
            //Return STALL if stop incorrect interface
            MMPS_3GPRECD_GetPreviewDisplay(&IsPreviewEnable);
            if(IsPreviewEnable && (gbCurrentSensor==1)) {
                RTNA_DBG_Str(3, "! v1.stop during v2 already start\r\n");
                usb_error();
                return;
            }
#endif

            usb_uvc_stop_preview();
            return;
        }
    } else if(USBInterface == UVC_D1_STREAM_IF2_NO) {
//dbg_printf(0, "!#%d\r\n", __LINE__);
    }
#if (SUPPORT_DUAL_DEVICE||SUPPORT_SWITCH_CAMERA)
    else if(USBInterface == UVC_D2_CTL_IF_NO) {

    } else if(USBInterface == UVC_D2_STREAM_IF1_NO) {
    
        //RTNA_DBG_Str3("VC.Cmd:");RTNA_DBG_Byte3(USBAlterSetting);RTNA_DBG_Str3("\r\n");
        
        if((gbUvcCommitted) && (USBAlterSetting/* == 0x01*/)) {
            RTNA_DBG_Str(3, "  set.v2.start\r\n");

#if BLOCK_2_UVC_INTERFACE
            //Return STALL if any interface already preview
                MMPS_3GPRECD_GetPreviewDisplay(&IsPreviewEnable);
                if(IsPreviewEnable) {
                dbg_printf(0, "! v2.start during interface %d already start\r\n", gbCurrentSensor);
                    usb_error(); //prevent host start before stop
                    return;
                }
#endif
            if(gbCurrentSensor!=1) {
                MMPF_Sensor_Set3AState(MMPF_SENSOR_3A_RESET);//sensor change! for gsSensorFunction->MMPF_Sensor_InitializeISP()==>ISP_IF_LIB_Init()
                MMPF_Sensor_SetBufferSize(0);
            }

			gbCurrentSensor = 1;//SensorFunction_Module1, 5M sensor
			usb_uvc_start_preview();
			return;				
        } else if((gbUvcCommitted) && (USBAlterSetting == 0x00)) {
            
            RTNA_DBG_Str(3, "  set.v2.stop\r\n");
            
#if BLOCK_2_UVC_INTERFACE
            //Return STALL if stop incorrect interface
            MMPS_3GPRECD_GetPreviewDisplay(&IsPreviewEnable);
            if(IsPreviewEnable && (gbCurrentSensor==0)) {
                RTNA_DBG_Str(3, "! v2.stop during v1 already start\r\n");
                usb_error();
                return;
            }
#endif

			usb_uvc_stop_preview();
        }
    } else if(USBInterface == UVC_D2_STREAM_IF2_NO) {

    }
#endif//SUPPORT_DUAL_DEVICE
#if SUPPORT_UAC
    else if(USBInterface == UAC_STREAM_IF_NO) {
		switch(USBAlterSetting) {
			case 0:
		            RTNA_DBG_Str(3, "  *[USB cmd]A_E_Q*\r\n");
                    PCAM_USB_SetAudioWorkMode(MMPF_AUDIO_WORK_MODE_UAC, MMPF_AUDIO_WORK_STATUS_SEND);                            
#if SUPPORT_WHQL_TEST
    			    USB_AudioPreviewStop(PCAM_API/*PCAM_NONBLOCKING*/);
#else
		            usb_uac_audio_stop();
#endif
		            break;
            case 1: // sample rate is AUDIN_SAMPLERATE defined in config_fw.h
            		RTNA_DBG_Str(3, "  *[USB cmd]A_S*\r\n");
#if SUPPORT_WHQL_TEST
                    MMPS_3GPRECD_GetPreviewDisplay(&IsPreviewEnable);
                    if(IsPreviewEnable == MMP_FALSE){
                		AlternateSamplingRate= pcam_audio->pCamSampleRate;
	    	            USB_AudioPreviewStart(PCAM_API/*PCAM_NONBLOCKING*/);
	    	        }
	    	        else{
                		usb_uac_audio_start();
	    	        }
#else
                    PCAM_USB_SetAudioWorkMode(MMPF_AUDIO_WORK_MODE_UAC, MMPF_AUDIO_WORK_STATUS_SEND);                            
            		usb_uac_audio_start();
#endif
					break;
		}
    }
#endif

    // UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
    USBEndpoint = 0;     
    USBInPhase = SET_INTERFACE_CMD;
    usb_ep0_null_in();
}

//*****************************************************************
// function : std_in_setinterface
// input    : none
// output   : none
//*****************************************************************
#if 0
void std_in_setinterface(void)
{
    //USBOutPhase = SET_INTERFACE_CMD;
    // usb_ep0_null_out();  
}

//*****************************************************************
// function : std_out_setinterface
// input    : none
// output   : none
//*****************************************************************
void std_out_setinterface(void)
{
}
#endif

//*****************************************************************
// function : std_setup_synchframe
// input    : none
// output   : none
//*****************************************************************
void std_setup_synchframe(void)
{
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
    
    if(UsbRequestPayload_wIndex==0)
    {
       UsbWriteEp0CSR(SET_EP0_SENDSTALL);       
    }
    else
    {
       pUSB_CTL->USB_FIFO_EP[0x0].FIFO_W = USBFrameNum;
       USBInPhase = SYNCH_FRAME_CMD;
       USBEP0TxCnt = 0x02;
       //    USBEP0TxAddr = USBEP0TxBufAddr;
       usb_ep0_in();
    }
}

//*****************************************************************
// function : std_in_syncframe
// input    : none
// output   : none
//*****************************************************************
void std_in_syncframe(void)
{
    USBOutPhase = SYNCH_FRAME_CMD;
    usb_ep0_null_out();
}

//*****************************************************************
// function : std_out_syncframe
// input    : none
// output   : none
//*****************************************************************
#if 0
void std_out_syncframe(void)
{
}
#endif
//*****************************************************************
// function : std_setup_getdevicedescriptor
// input    : none
// output   : none
//*****************************************************************
void std_setup_getdevicedescriptor(void)
{
#if USE_COMMON_EP0_IN == 0
    MMP_UBYTE tmp;
    MMP_USHORT i;
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    tmp = UsbRequestPayload_wLength;
#endif

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);

#if USE_COMMON_EP0_IN
    USBEP0TxCnt = UsbRequestPayload_wLength;
    #if USE_SIMPLIFIED_DESC
    usb_vc_put_ep0_at_most(GET_DEV_DESCR_CMD, 0x12, DEVICE_DESCRIPTOR_DATA1);
    #else
    usb_vc_put_ep0_at_most(GET_DEV_DESCR_CMD, 0x12, USBDescBufAddr + DEVICE_DESCRIPTOR_DATA1);
    #endif
#else
    if(tmp < 0x12) {
        USBEP0TxCnt = tmp;
    } else {
        USBEP0TxCnt = 0x12;
    }

    for(i = 0;i < USBEP0TxCnt;i++) {
        pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = USBDescBufAddr[DEVICE_DESCRIPTOR_DATA1_ADDR + i];
    }
    USBInPhase = GET_DEV_DESCR_CMD;
    usb_ep0_in();
#endif
}


//*****************************************************************
// function : std_in_getdevicedescriptor
// input    : none
// output   : none
//*****************************************************************
void std_in_getdevicedescriptor(void)
{
    USBOutPhase = GET_DEV_DESCR_CMD;
    usb_ep0_null_out();
}

//*****************************************************************
// function : std_in_getdevquadescriptor
// input    : none
// output   : none
//*****************************************************************
void std_in_getdevquadescriptor(void)
{
    USBOutPhase = GET_DEVQUA_DESCR_CMD;
    usb_ep0_null_out();
}

//*****************************************************************
// function : std_out_getdevicedescriptor
// input    : none
// output   : none
//*****************************************************************
#if 0
void std_out_getdevicedescriptor(void)
{
}

//*****************************************************************
// function : std_out_getdevquadescriptor
// input    : none
// output   : none
//*****************************************************************
void std_out_getdevquadescriptor(void)
{
}
#endif
//*****************************************************************
// function : std_setup_getdevicequalifierdescriptor
// input    : none
// output   : none
//*****************************************************************
void std_setup_getdevicequalifierdescriptor(void)
{
#if USE_COMMON_EP0_IN
    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
    USBEP0TxCnt = UsbRequestPayload_wLength;
    usb_vc_put_ep0_at_most(GET_DEV_DESCR_CMD, 0x0A, DEVICE_QUALIFIER_DESCRIPTOR_DATA1);
#else
    MMP_UBYTE tmp;
    MMP_USHORT i;
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    tmp = UsbRequestPayload_wLength;
    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
    if(tmp < 0x0A) {
        USBEP0TxCnt = tmp;
    } else {
        USBEP0TxCnt = 0x0A;
    }
#if USE_COMMON_EP0_IN
    #if USE_SIMPLIFIED_DESC
    USBEP0TxCnt = UsbRequestPayload_wLength;
    usb_vc_put_ep0_data(GET_DEV_DESCR_CMD, tmp, DEVICE_QUALIFIER_DESCRIPTOR_DATA1);
    #endif
#else
    for(i = 0;i < USBEP0TxCnt;i++) {
         {
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = USBDescBufAddr[DEVICE_QUALIFIER_DESCRIPTOR_DATA1_ADDR + i];
        }
    }
#endif

    USBInPhase = GET_DEVQUA_DESCR_CMD;
    usb_ep0_in();
#endif
}


//*****************************************************************
// function : std_in_getdevicequalifierdescriptor
// input    : none
// output   : none
//*****************************************************************
void std_in_getdevicequalifierdescriptor(void)
{
    USBOutPhase = GET_DEVQUA_DESCR_CMD;
    usb_ep0_null_out();
}

#if 0
//*****************************************************************
// function : std_out_getdevicequalifierdescriptor
// input    : none
// output   : none
//*****************************************************************
void std_out_getdevicequalifierdescriptor(void)
{
}
#endif

#if USE_COMMON_EP0_IN && USE_SIMPLIFIED_DESC
void std_setup_prepare_config_desc(void)
{
    MMP_USHORT length;

    length = (MMP_USHORT) (USBConfigDescLen);
    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);

    EP0TXOffset = 0;
    gbEP0NotEnd = 0;

    // Get min of the length
    USBEP0TxCnt = UsbRequestPayload_wLength;
    if (length < USBEP0TxCnt) {
        USBEP0TxCnt = length;
    }
    USBConfigDescLen = USBEP0TxCnt;

    if (USBEP0TxCnt < 0x40) {
    } else {
        USBEP0TxCnt = 0x40;
        gbEP0NotEnd = 1;
    }

    USBConfigDescLen -= USBEP0TxCnt;
    EP0TXOffset += USBEP0TxCnt;
}
#endif

//*****************************************************************
// function : std_setup_getdevicedescriptor
// input    : none
// output   : none
//*****************************************************************
void std_setup_getotherspeedconfigdescriptor(void)
{
#if USE_COMMON_EP0_IN && USE_SIMPLIFIED_DESC
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    std_setup_prepare_config_desc();
    if (gbUsbHighSpeed) {
        gbUsbOtherSpeed = 0;
    } else {
        gbUsbOtherSpeed = 1;
    }
    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0x09;
    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0x07; // change to other speed
#if SUPPORT_SWITCH_CAMERA
    if(gbUsbHighSpeed) {
        usb_vc_put_ep0_data(GET_OTHERSP_DESCR_CMD, USBEP0TxCnt-2, gpUsbDesc[0]+2);
    } else {
        usb_vc_put_ep0_data(GET_OTHERSP_DESCR_CMD, USBEP0TxCnt-2, gpUsbDesc[1 + gbSwitchSensor]+2);
    }
#else
    usb_vc_put_ep0_data(GET_OTHERSP_DESCR_CMD, USBEP0TxCnt-2, gpUsbDesc[1 - gbUsbHighSpeed]+2);
#endif
#else
    MMP_USHORT tmp,length;
    MMP_USHORT i;
    //MMP_UBYTE tmpspeed;
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;    

    EP0TXOffset = 0;

    tmp = UsbRequestPayload_wLength;

    length = (MMP_USHORT) (USBConfigDescLen);

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);

    //tmpspeed = gbUsbHighSpeed;

    if(gbUsbHighSpeed) {
        gbUsbOtherSpeed = 0;
    } else {
        gbUsbOtherSpeed = 1;
    }

    gbEP0NotEnd = 0;

    if(tmp < 0x40) {
        if(length < tmp) {
            USBEP0TxCnt = length; 
            USBConfigDescLen = 0;
        } else {
            USBEP0TxCnt = tmp; 
            USBConfigDescLen = 0;
        }
    } else {
        if(length >= 0x40) {
            USBEP0TxCnt = 0x40; 
            if(length > tmp) {
                USBConfigDescLen = tmp;
            } else {
                USBConfigDescLen = length;
            }
            USBConfigDescLen -= 0x40;

            gbEP0NotEnd = 1;
        } else {
            USBEP0TxCnt = length; 
            USBConfigDescLen = 0;
        }
    }

    if(gbUsbOtherSpeed) {  // HS
        //HS_CONFIG_DESCRIPTOR_DATA1[1] = 0x07; // other speed 

        for(i = 0;i < USBEP0TxCnt;i++) {
            if(i == 1) {// type
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0x07; // other speed 
            } else {
#if SUPPORT_SWITCH_CAMERA
                if(gbSwitchSensor==MAIN_SENSOR) {
                    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = HS_CONFIG_DESCRIPTOR_DATA1[i];
                } else {
                    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = HS_CONFIG_DESCRIPTOR_DATA2[i];
                }
#else
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = HS_CONFIG_DESCRIPTOR_DATA1[i];
#endif
            }
        }
    }
    else{  // FS
        //CONFIG_DESCRIPTOR_DATA1[1] = 0x07; // other speed 

        for(i = 0;i < USBEP0TxCnt;i++) {
            if(i == 1) // type
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0x07; // other speed 
            else
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = CONFIG_DESCRIPTOR_DATA1[i];
        }
    }

    EP0TXOffset += USBEP0TxCnt;
    USBInPhase = GET_OTHERSP_DESCR_CMD;
    usb_ep0_in();
#endif
}


//*****************************************************************
// function : std_in_getdevicedescriptor
// input    : none
// output   : none
//*****************************************************************
void std_in_get_config_descriptor(u_char cmd, u_char* desc_hs, u_char* desc_os)
{
    u_char *data;

    if(USBConfigDescLen == 0)
    {
        USBOutPhase = cmd;
    }
    else {
        USBEP0TxCnt = USBConfigDescLen;

#if 0
        if(USBConfigDescLen <= 0x40) {
            gbEP0NotEnd = 0;
        }
        else {
            USBEP0TxCnt = 0x40;
        }
        if(gbUsbHighSpeed)
        {
            data = desc_hs + EP0TXOffset;
        }
        else {
            data = desc_os + EP0TXOffset;
        }

        usb_vc_put_ep0_data(cmd, USBEP0TxCnt, data);
#else
        if (USBConfigDescLen <= 0x40) {
            gbEP0NotEnd = 0;
        }
        if(gbUsbHighSpeed)
        {
            data = desc_hs;
        }
        else {
            data = desc_os;
        }
        usb_vc_put_ep0_at_most(cmd, 0x40, data + EP0TXOffset);
#endif
        EP0TXOffset+=USBEP0TxCnt;
        USBConfigDescLen -= USBEP0TxCnt;
    }
}
void std_in_getotherspeedconfigdescriptor(void)
{
#if USE_COMMON_EP0_IN
#if SUPPORT_SWITCH_CAMERA
    if(gbSwitchSensor==MAIN_SENSOR) {
    std_in_get_config_descriptor(GET_OTHERSP_DESCR_CMD, CONFIG_DESCRIPTOR_DATA1, HS_CONFIG_DESCRIPTOR_DATA1);
    } else {
        std_in_get_config_descriptor(GET_OTHERSP_DESCR_CMD, CONFIG_DESCRIPTOR_DATA1, HS_CONFIG_DESCRIPTOR_DATA2);
    }
#else
    std_in_get_config_descriptor(GET_OTHERSP_DESCR_CMD, CONFIG_DESCRIPTOR_DATA1, HS_CONFIG_DESCRIPTOR_DATA1);
#endif
#else
    MMP_USHORT i;
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;    

    if(USBConfigDescLen == 0) {
        //usb_desc_init();
        USBOutPhase = GET_OTHERSP_DESCR_CMD;
        usb_ep0_null_out();
        // std_out_getotherspeedconfigdescriptor(); avoid lost out int
    } else {
        if(USBConfigDescLen < 0x40) {
            USBEP0TxCnt = USBConfigDescLen;
            USBConfigDescLen = 0;
            gbEP0NotEnd = 0;
        } else {
            USBConfigDescLen -= 0x40;
            USBEP0TxCnt = 0x40;
        }
        if(gbUsbOtherSpeed) {  // HS
#if SUPPORT_SWITCH_CAMERA
            if(gbSwitchSensor==MAIN_SENSOR) {
            for(i = 0;i < USBEP0TxCnt;i++) {
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = HS_CONFIG_DESCRIPTOR_DATA1[i + EP0TXOffset];
            }
            } else {
                for(i = 0;i < USBEP0TxCnt;i++) {
                    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = HS_CONFIG_DESCRIPTOR_DATA2[i + EP0TXOffset];
                }
            }
#else
            for(i = 0;i < USBEP0TxCnt;i++) {
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = HS_CONFIG_DESCRIPTOR_DATA1[i + EP0TXOffset];
            }
#endif
        }
        else{  // FS
            for(i = 0;i < USBEP0TxCnt;i++) {
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = CONFIG_DESCRIPTOR_DATA1[i + EP0TXOffset];
            }
        } 
        EP0TXOffset += USBEP0TxCnt;        
        USBInPhase = GET_OTHERSP_DESCR_CMD;
        usb_ep0_in();
    }
#endif
}

//*****************************************************************
// function : std_out_getotherspeedconfigdescriptor
// input    : none
// output   : none
//*****************************************************************
#if USE_REQUEST_FUNC_MAP == 0
void std_out_getotherspeedconfigdescriptor(void)
{
    //usb_desc_init();
    USBConfigDescLen = USBConfig1Len;
}
#endif
//*****************************************************************
// function : std_setup_getstringdescriptor
// input    : none
// output   : none
//*****************************************************************
void std_setup_getstringdescriptor(void)
{
#if USE_SIMPLIFIED_DESC
    MMP_UBYTE idx;
    static u_char *const str[] = {
        LANGUAGE_ID_DATA, //0
        MANUFACTURER_STRING_DATA, //1
        PRODUCT_STRING_DATA, //2
        SERIALNUMBER_STRING_DATA, //3
    #if (SUPPORT_DUAL_DEVICE||SUPPORT_SWITCH_CAMERA)
        PRODUCT_STRING2_DATA, //4
    #endif
    };
    MMP_UBYTE *ptr;

    idx = UsbRequestPayload_wValue & 0xFF;
    USBEP0TxCnt = UsbRequestPayload_wLength;

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);

    if (idx >= (sizeof(str) / sizeof(str[0])))
    {
        usb_error();
        return;
    }
    ptr = str[idx];

    #if USE_COMMON_EP0_IN
        usb_vc_put_ep0_at_most(GET_STRING_DESCR_CMD, ptr[0], ptr);
    #else
        #error not implemented yet
    #endif
#else
    MMP_USHORT tmp,length;
    MMP_UBYTE i;
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;    

    tmp = UsbRequestPayload_wValue & 0xFF;
    length = UsbRequestPayload_wLength;  

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);

    if(tmp == 0) {
        if(length > UsbDescriptorInfo.pStrDescriptor0[0]) {
            USBEP0TxCnt = UsbDescriptorInfo.pStrDescriptor0[0];
        } else {
            USBEP0TxCnt = length;
        }
        for(i = 0;i < USBEP0TxCnt;i++) {
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = USBDescBufAddr[UsbDescriptorInfo.StrDescriptor0Offset + i];
        }
        USBInPhase = GET_STRING_DESCR_CMD;
        usb_ep0_in();
    } else if(tmp == 0x01) {
        tmp = length;
        if(tmp < UsbDescriptorInfo.pStrDescriptor1[0]) {
            USBEP0TxCnt = tmp;
        } else {
            USBEP0TxCnt = UsbDescriptorInfo.pStrDescriptor1[0];
        }
        for(i = 0;i < USBEP0TxCnt;i++) {
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = USBDescBufAddr[UsbDescriptorInfo.StrDescriptor1Offset + i];
        }
        USBInPhase = GET_STRING_DESCR_CMD;
        usb_ep0_in();
    } else if(tmp == 0x02) {
        tmp = length;
        if(tmp < UsbDescriptorInfo.pStrDescriptor2[0]) {
            USBEP0TxCnt = tmp;
        } else {
            USBEP0TxCnt = UsbDescriptorInfo.pStrDescriptor2[0];
        }
        for(i = 0;i < USBEP0TxCnt;i++) {
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = USBDescBufAddr[UsbDescriptorInfo.StrDescriptor2Offset + i];
        }
        USBInPhase = GET_STRING_DESCR_CMD;
        usb_ep0_in();
    } else if(tmp == 0x03) {
        USBEP0TxCnt = (length<UsbDescriptorInfo.pStrDescriptor3[0])?length:UsbDescriptorInfo.pStrDescriptor3[0];
        for(i = 0;i < USBEP0TxCnt;i++) {
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = USBDescBufAddr[UsbDescriptorInfo.StrDescriptor3Offset + i];
        }
        USBInPhase = GET_STRING_DESCR_CMD;
        usb_ep0_in();
    } else {
        usb_error();
    }
#endif
}

//*****************************************************************
// function : std_in_getstringdescriptor
// input    : none
// output   : none
//*****************************************************************
void std_in_getstringdescriptor(void)
{
    USBOutPhase = GET_STRING_DESCR_CMD;
    usb_ep0_null_out();
}

//*****************************************************************
// function : std_out_getstringdescriptor
// input    : none
// output   : none
//*****************************************************************
#if 0
void std_out_getstringdescriptor(void)
{
}
#endif
//*****************************************************************
// function : std_setup_getconfigurationdescriptor
// input    : none
// output   : none
//*****************************************************************
void std_setup_getconfigurationdescriptor(void)
{
#if USE_COMMON_EP0_IN && USE_SIMPLIFIED_DESC
    std_setup_prepare_config_desc();
#else
    MMP_USHORT tmp,length;
    MMP_USHORT i;
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;   

    EP0TXOffset = 0;

    tmp = UsbRequestPayload_wLength;

    length = (MMP_USHORT) (USBConfigDescLen);

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);

    gbEP0NotEnd = 0;

#if 1
    // Get min of the length, tmp: bytes to be sent.
    USBEP0TxCnt = UsbRequestPayload_wLength;//tmp;
    if (length < USBEP0TxCnt) {
        USBEP0TxCnt = length;
    }
    USBConfigDescLen = USBEP0TxCnt;
    #if 1
    if (USBEP0TxCnt < 0x40) {
    } else {
        USBEP0TxCnt = 0x40;
        gbEP0NotEnd = 1;
    }
    #endif
    USBConfigDescLen -= USBEP0TxCnt;
    EP0TXOffset += USBEP0TxCnt;

#else
    if(tmp <= 0x40) {
        if(length < tmp) {
            USBEP0TxCnt = length; 
            USBConfigDescLen = 0;
        } else {
            USBEP0TxCnt = tmp; 
            USBConfigDescLen = 0;
        }
    } else {
        if(length >= 0x40) {
            USBEP0TxCnt = 0x40; 
            if(length > tmp) {
                USBConfigDescLen = tmp;
            } else {
                USBConfigDescLen = length;
            }
            USBConfigDescLen -= 0x40;

            gbEP0NotEnd = 1;
        } else {
            USBEP0TxCnt = length; 
            USBConfigDescLen = 0;
        }
    }
#endif
#endif
#if USE_SIMPLIFIED_DESC
    #if USE_COMMON_EP0_IN
#if SUPPORT_SWITCH_CAMERA
    if(gbUsbHighSpeed) {
        usb_vc_put_ep0_data(GET_CONFIG_DESCR_CMD, USBEP0TxCnt, gpUsbDesc[gbUsbHighSpeed + gbSwitchSensor]);
    } else {
        usb_vc_put_ep0_data(GET_CONFIG_DESCR_CMD, USBEP0TxCnt, gpUsbDesc[gbUsbHighSpeed]);
    }
#else
    usb_vc_put_ep0_data(GET_CONFIG_DESCR_CMD, USBEP0TxCnt, gpUsbDesc[gbUsbHighSpeed]);
#endif
    //usb_vc_put_ep0_at_most(GET_CONFIG_DESCR_CMD, 0x40, gpUsbDesc[gbUsbHighSpeed]);
    #else
    for(i = 0;i < USBEP0TxCnt;i++) {
        pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = USBDescBufAddr[CONFIG_DESCRIPTOR_DATA1_ADDR + i];
    }
    USBInPhase = GET_CONFIG_DESCR_CMD;
    usb_ep0_in();
    #endif
#else
    #if USE_COMMON_EP0_IN
    usb_vc_put_ep0_data(GET_CONFIG_DESCR_CMD, USBEP0TxCnt, USBDescBufAddr + CONFIG_DESCRIPTOR_DATA1_ADDR);
    #else
    for(i = 0;i < USBEP0TxCnt;i++) {
        pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = USBDescBufAddr[CONFIG_DESCRIPTOR_DATA1_ADDR + i];
    }
    USBInPhase = GET_CONFIG_DESCR_CMD;
    usb_ep0_in();
    #endif
#endif
    //EP0TXOffset += USBEP0TxCnt;
} 
//*****************************************************************
// function : std_in_getconfigurationdescriptor
// input    : none
// output   : none
//*****************************************************************
void std_in_getconfigurationdescriptor(void)
{
#if USE_COMMON_EP0_IN
#if SUPPORT_SWITCH_CAMERA
    if(gbSwitchSensor==MAIN_SENSOR) {
    std_in_get_config_descriptor(GET_CONFIG_DESCR_CMD, HS_CONFIG_DESCRIPTOR_DATA1, CONFIG_DESCRIPTOR_DATA1);
    } else {
        std_in_get_config_descriptor(GET_CONFIG_DESCR_CMD, HS_CONFIG_DESCRIPTOR_DATA2, CONFIG_DESCRIPTOR_DATA1);
    }
#else
    std_in_get_config_descriptor(GET_CONFIG_DESCR_CMD, HS_CONFIG_DESCRIPTOR_DATA1, CONFIG_DESCRIPTOR_DATA1);
#endif
#else
    MMP_USHORT  i;
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    if(USBConfigDescLen == 0) {
        USBOutPhase = GET_CONFIG_DESCR_CMD;
        gbEP0NotEnd = 0;
        usb_ep0_null_out();
        //        std_out_getconfigurationdescriptor();
    } else {
        if(USBConfigDescLen <= 0x40) {
            USBEP0TxCnt = USBConfigDescLen;
            USBConfigDescLen = 0;
            gbEP0NotEnd = 0;
        } else {
            USBConfigDescLen -= 0x40;
            USBEP0TxCnt = 0x40;
        }
        #if USE_SIMPLIFIED_DESC
#if SUPPORT_SWITCH_CAMERA
        if(gbUsbHighSpeed) {
            usb_vc_put_ep0_data(GET_CONFIG_DESCR_CMD, USBEP0TxCnt, gpUsbDesc[gbUsbHighSpeed + gbSwitchSensor]+EP0TXOffset);
        } else
#endif
        {
        usb_vc_put_ep0_data(GET_CONFIG_DESCR_CMD, USBEP0TxCnt, gpUsbDesc[gbUsbHighSpeed]+EP0TXOffset);
        }

        #if USE_COMMON_EP0_IN
        #else
        for(i = 0;i < USBEP0TxCnt;i++) {
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = gpUsbDesc[gbUsbHighSpeed][i + EP0TXOffset];
        }
        #endif
        #else
        for(i = 0;i < USBEP0TxCnt;i++) {
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = USBDescBufAddr[CONFIG_DESCRIPTOR_DATA1_ADDR + i + EP0TXOffset];
        }
        #endif
        EP0TXOffset += USBEP0TxCnt;        
        USBInPhase = GET_CONFIG_DESCR_CMD;
        usb_ep0_in();
    }
#endif
}


//*****************************************************************
// function : std_out_getconfigurationdescriptor
// input    : none
// output   : none
//*****************************************************************
#if USE_REQUEST_FUNC_MAP == 0
void std_out_getconfigurationdescriptor(void)
{
    USBConfigDescLen = USBConfig1Len;
}
#endif

#if SUPPORT_HID_FUNC
//*****************************************************************
// function : std_setup_getreportdescriptor
// input    : none
// output   : none
//*****************************************************************
void std_setup_getreportdescriptor(void)
{
    MMP_USHORT tmp,length;
    MMP_USHORT i;
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;   

    EP0TXOffset = 0;

    tmp = UsbRequestPayload_wLength;

    length = (MMP_USHORT) (USBReportDescLen);

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);

    gbEP0NotEnd = 0;

    if(tmp <= 0x40) {
        if(length < tmp) {
            USBEP0TxCnt = length; 
            USBReportDescLen = 0;
        } else {
            USBEP0TxCnt = tmp; 
            USBReportDescLen = 0;
        }
    } else {
        if(length >= 0x40) {
            USBEP0TxCnt = 0x40; 
            if(length > tmp) {
                USBReportDescLen = tmp;
            } else {
                USBReportDescLen = length;
            }
            USBReportDescLen -= 0x40;

            gbEP0NotEnd = 1;
        } else {
            USBEP0TxCnt = length; 
            USBReportDescLen = 0;
        }
    }
    for(i = 0;i < USBEP0TxCnt;i++) {
        pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = HID_REPORT_DSCR_DATA[i];
    }
    EP0TXOffset += USBEP0TxCnt;
    USBInPhase = GET_HIDREPORT_DESCR_CMD;
    usb_ep0_in();
} 
//*****************************************************************
// function : std_in_getreportdescriptor
// input    : none
// output   : none
//*****************************************************************
void std_in_getreportdescriptor(void)
{
    MMP_USHORT  i;
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    if(USBReportDescLen == 0) {
        USBOutPhase = GET_HIDREPORT_DESCR_CMD;
        gbEP0NotEnd = 0;
        usb_ep0_null_out();
        //        std_out_getconfigurationdescriptor();
    } else {
        if(USBReportDescLen <= 0x40) {
            USBEP0TxCnt = USBReportDescLen;
            USBReportDescLen = 0;
            gbEP0NotEnd = 0;
        } else {
            USBReportDescLen -= 0x40;
            USBEP0TxCnt = 0x40;
        }
        for(i = 0;i < USBEP0TxCnt;i++) {
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = HID_REPORT_DSCR_DATA[i + EP0TXOffset];
        } 
        EP0TXOffset += USBEP0TxCnt;        
        USBInPhase = GET_HIDREPORT_DESCR_CMD;
        usb_ep0_in();
    }
}
//*****************************************************************
// function : std_out_getreportdescriptor
// input    : none
// output   : none
//*****************************************************************
void std_out_getreportdescriptor(void)
{
    USBReportDescLen = REPORT_DESCRIPTOR_LEN;
}
#endif

#if USE_REQUEST_FUNC_MAP
/** use 0 for not calling any function without reporting error
    use usb_error to report error (usb_error) */
typedef void (*REQUEST_FUNCTION) (void);
#endif
//*****************************************************************
// function : std_request_setup 
// input    : none
// output   : none
//*****************************************************************
void std_request_setup(void)
{
#if USE_REQUEST_FUNC_MAP
    // save 48 bytes code
    u_char tmp,tmp2;

    //see the type description for more info
    static const REQUEST_FUNCTION funcs[] =
    {
        std_setup_getstatus,//0x00
        std_setup_clearfeature,//0x01
        usb_error,//0x02
        std_setup_setfeature,//0x03
        usb_error,//0x04
        std_setup_setaddress,//0x05
        usb_error,//0x06, should use get_desc_funcs instead
        std_setup_setdescriptor,//0x07
        std_setup_getconfiguration,//0x08
        std_setup_setconfiguration,//0x09
        std_setup_getinterface,//0x0A
        std_setup_setinterface,//0x0B
        std_setup_synchframe,//0x0C
    };
    #define MAX_FUNCTION_IDX SYNCH_FRAME

    static const REQUEST_FUNCTION get_desc_funcs[] =
    {
        usb_error,//0x00
        std_setup_getdevicedescriptor,//0x01
        std_setup_getconfigurationdescriptor,//0x02
        std_setup_getstringdescriptor,//0x03
        usb_error,//0x04
        usb_error,//0x05
        std_setup_getdevicequalifierdescriptor,//0x06
        std_setup_getotherspeedconfigdescriptor,//0x07
#if SUPPORT_HID_FUNC
        std_setup_getreportdescriptor,//0x08
#endif
    };
    #define MAX_DESC_FUNCTION_IDX OTHER_SPEED_CONFIG_DESC

    tmp = UsbRequestPayload_bRequest;
    tmp2 = (UsbRequestPayload_wValue >> 8);

    //the functions starts with 0x60(STD_CMD)
    if (tmp > MAX_FUNCTION_IDX)
    {
        usb_error();
    }
    else if (GET_DESCRIPTOR == tmp)
    {
        if (tmp2 > MAX_DESC_FUNCTION_IDX) {
#if SUPPORT_HID_FUNC
            if(tmp2 == REPORT_DESC){
                if (get_desc_funcs[8] != 0)
                    get_desc_funcs[8]();
            }
            else
#endif
            usb_error();
        }
        else {
            if (get_desc_funcs[tmp2] != 0)
            {
                get_desc_funcs[tmp2]();
            }
        }
    }
    else {
        if (funcs[tmp] != 0)
        {
            funcs[tmp]();
        }
    }
#else
    MMP_UBYTE tmp,tmp2;
    tmp = UsbRequestPayload_bRequest;
    tmp2 = (UsbRequestPayload_wValue >> 8);

    if(tmp == GET_STATUS) {
        std_setup_getstatus();
    } else if(tmp == SET_ADDRESS) {
        std_setup_setaddress();
    } else if(tmp == GET_DESCRIPTOR) {
        if(tmp2 == DEVICE_DESCR) {
            std_setup_getdevicedescriptor();
        } else if(tmp2 == CONFIG_DESCR) {
            std_setup_getconfigurationdescriptor();
        } else if(tmp2 == STRING_DESCR) {
            std_setup_getstringdescriptor();
        } else if(tmp2 == INTERFACE_DESCR) {
            usb_error();
        } else if(tmp2 == ENDPOINT_DESCR) {
            usb_error();
        } else if(tmp2 == DEVICE_QUALIFIER_DESCR) {
            std_setup_getdevicequalifierdescriptor();
        } else if(tmp2 == OTHER_SPEED_CONFIG_DESC) {
            std_setup_getotherspeedconfigdescriptor();
        } else if(tmp2 == INTERFACE_POWER_DESC) {
            usb_error();
        } else {
            usb_error();
        }
    } else if(tmp == SET_DESCRIPTOR) {
        std_setup_setdescriptor();
    } else if(tmp == CLEAR_FEATURE) {
        std_setup_clearfeature();
    } else if(tmp == SET_FEATURE) {
        std_setup_setfeature();
    } else if(tmp == GET_INTERFACE) {
        std_setup_getinterface();
    } else if(tmp == SET_INTERFACE) {
        std_setup_setinterface();
    } else if(tmp == GET_CONFIGURATION) {
        std_setup_getconfiguration();
    } else if(tmp == SET_CONFIGURATION) {
        std_setup_setconfiguration();
    } else if(tmp == SYNCH_FRAME) {
        std_setup_synchframe();
    } else {
        usb_error();
    }
#endif
}

//*****************************************************************
// function : std_request_in
// input    : none
// output   : none
//*****************************************************************
void std_request_in(void)
{
#if USE_REQUEST_FUNC_MAP
    //save 30 bytes
    //see the type description for more info
    static const REQUEST_FUNCTION funcs[] =
    {
        std_in_getstatus,//0x60
        std_in_clearfeature,//0x61
        0,//std_in_setfeature,//0x62
        std_in_setaddress,//0x63
        usb_error,//0x64
        std_in_setdescriptor,//0x65
        0,//std_in_getconfiguration,//0x66
        0,//std_in_setconfiguration,//0x67
        std_in_getinterface,//0x68
        0,//std_in_setinterface,//0x69
        std_in_syncframe,//0x6a
        std_in_getdevicedescriptor,//0x6B
        std_in_getconfigurationdescriptor,//0x6C
        std_in_getstringdescriptor,//0x6D
        std_in_getdevquadescriptor,//0x6E
        std_in_getotherspeedconfigdescriptor,//0x6F
#if SUPPORT_HID_FUNC
        std_in_getreportdescriptor,//0x70
#endif
    };

    //the functions starts with 0x60(STD_CMD)
    if ((USBCmd < STD_CMD) || (USBCmd > (GET_OTHERSP_DESCR_CMD+SUPPORT_HID_FUNC)))
    {
        usb_error();
    }
    else {
        if (0 != funcs[USBCmd - STD_CMD])
        {
            funcs[USBCmd - STD_CMD]();
        }
    }
#else
    if(USBCmd == GET_DEV_DESCR_CMD) {
        std_in_getdevicedescriptor();
    } else if(USBCmd == GET_CONFIG_DESCR_CMD) {
        std_in_getconfigurationdescriptor();
    } else if(USBCmd == GET_STRING_DESCR_CMD) {
        std_in_getstringdescriptor();
    } else if(USBCmd == SET_DESCRIPTOR_CMD) {
        std_in_setdescriptor();
    } else if(USBCmd == GET_CONFIG_CMD) {
        std_in_getconfiguration();
    } else if(USBCmd == SET_CONFIG_CMD) {
        //std_in_setconfiguration();
    } else if(USBCmd == GET_INTERFACE_CMD) {
        std_in_getinterface();
    } else if(USBCmd == SET_INTERFACE_CMD) {
        //std_in_setinterface();
    } else if(USBCmd == GET_STATUS_CMD) {
        std_in_getstatus();
    } else if(USBCmd == CLEAR_FEATURE_CMD) {
        std_in_clearfeature();
    } else if(USBCmd == SET_FEATURE_CMD) {
        //std_in_setfeature();
    } else if(USBCmd == SET_ADDRESS_CMD) {
        std_in_setaddress();
    } else if(USBCmd == SYNCH_FRAME_CMD) {
        std_in_syncframe();
    } else if(USBCmd == GET_DEVQUA_DESCR_CMD) {
        std_in_getdevquadescriptor();
    } else if(USBCmd == GET_OTHERSP_DESCR_CMD) {
        std_in_getotherspeedconfigdescriptor();
    } else {
        usb_error();
    }
#endif
}

//*****************************************************************
// function : std_request_out
// input    : none
// output   : none
//*****************************************************************
void std_request_out(void)
{
#if USE_REQUEST_FUNC_MAP
    if ((USBCmd < STD_CMD) || (USBCmd > GET_OTHERSP_DESCR_CMD+SUPPORT_HID_FUNC) || (USBCmd == GET_DESCRIPTOR_CMD))
    {
        usb_error();
    } else if(USBCmd == GET_CONFIG_DESCR_CMD) {
        USBConfigDescLen = USBConfig1Len;//std_out_getconfigurationdescriptor();
    } else if(USBCmd == GET_OTHERSP_DESCR_CMD) {
        USBConfigDescLen = USBConfig1Len; //std_out_getotherspeedconfigdescriptor();
#if SUPPORT_HID_FUNC
    } else if(USBCmd == GET_HIDREPORT_DESCR_CMD) {
        USBReportDescLen = USBConfig1Len;//std_out_getreportdescriptor();
#endif
    }
#else
    if(USBCmd == GET_STATUS_CMD) {
        //std_out_getstatus();
    } else if(USBCmd == CLEAR_FEATURE_CMD) {
        //std_out_clearfeature();
    } else if(USBCmd == SET_FEATURE_CMD) {
        //std_out_setfeature();
    } else if(USBCmd == SET_ADDRESS_CMD) {
        //std_out_setaddress();
    } else if(USBCmd == GET_DEV_DESCR_CMD) {
        //std_out_getdevicedescriptor();
    } else if(USBCmd == GET_CONFIG_DESCR_CMD) {
        std_out_getconfigurationdescriptor();
    } else if(USBCmd == GET_STRING_DESCR_CMD) {
        //std_out_getstringdescriptor();
    } else if(USBCmd == SET_DESCRIPTOR_CMD) {
        //std_out_setdescriptor();
    } else if(USBCmd == GET_CONFIG_CMD) {
        //std_out_getconfiguration();
    } else if(USBCmd == SET_CONFIG_CMD) {
        //std_out_setconfiguration();
    } else if(USBCmd == GET_INTERFACE_CMD) {
        //std_out_getinterface();
    } else if(USBCmd == SET_INTERFACE_CMD) {
        //std_out_setinterface();
    } else if(USBCmd == SYNCH_FRAME_CMD) {
        //std_out_syncframe();
    } else if(USBCmd == GET_DEVQUA_DESCR_CMD) {
        //std_out_getdevquadescriptor();
    } else if(USBCmd == GET_OTHERSP_DESCR_CMD) {
        std_out_getotherspeedconfigdescriptor();
    } else {
        usb_error();
    }
#endif
    //    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
}


#else
//------------------------------------------------------------------------------
//  Function    : UsbProcessStdCmd
//  Parameter   : None
//  Return Value : None
//  Description :
//------------------------------------------------------------------------------
void UsbProcessStdCmd(void)
{
    MMP_UBYTE request,type,index;
    MMP_USHORT size,csr;

    request = UsbRequestPayload.bRequest;

    //    RTNA_DBG_Str(0,"Std Request:");
    //    RTNA_DBG_Byte(0,request);
    //    RTNA_DBG_Str(0,"\r\n");

    switch(request) {
    case STD_GET_DESCRIPTOR_CMD:
        type = (UsbRequestPayload.wValue >> 8);
        size = UsbRequestPayload.wLength;
        index = (UsbRequestPayload.wValue & 0xFF);

        glUsbCtlTxCnt = size;
        switch(type) {
        case DEVICE_DESCRIPTOR:
            if(UsbDescriptorInfo.DeviceDescriptorSize < size)
                glUsbCtlTxCnt = UsbDescriptorInfo.DeviceDescriptorSize;
            break;
        case DEVICE_QUALIFIER_DESCRIPTOR:
            if(UsbDescriptorInfo.DeviceQualifierDescriptorSize < size)
                glUsbCtlTxCnt = UsbDescriptorInfo.DeviceQualifierDescriptorSize;
            break;
        case OTHER_SPEED_CONFIGURATION_DESCRIPTOR:
            if(UsbDescriptorInfo.OtherSpeedConfigDescriptorSize < size)
                glUsbCtlTxCnt = UsbDescriptorInfo.OtherSpeedConfigDescriptorSize;
            break;
        case CONFIGURATION_DESCRIPTOR:
            if(UsbDescriptorInfo.ConfigDescriptorSize < size)
                glUsbCtlTxCnt = UsbDescriptorInfo.ConfigDescriptorSize;
            break;
        case STRING_DESCRIPTOR:
            switch(index) {
            case 0:
                if(UsbDescriptorInfo.StrDescriptor0Size < size)
                    glUsbCtlTxCnt = UsbDescriptorInfo.StrDescriptor0Size;
                break;
            case 1:
                if(UsbDescriptorInfo.StrDescriptor1Size < size)
                    glUsbCtlTxCnt = UsbDescriptorInfo.StrDescriptor1Size;
                break;
            case 2:
                if(UsbDescriptorInfo.StrDescriptor2Size < size)
                    glUsbCtlTxCnt = UsbDescriptorInfo.StrDescriptor2Size;
                break;
            case 3:
                if(UsbDescriptorInfo.StrDescriptor3Size < size)
                    glUsbCtlTxCnt = UsbDescriptorInfo.StrDescriptor3Size;
                break;
            case 0xEE:
                //Microsoft OS String Descriptor
                if(UsbDescriptorInfo.StrDescriptor4Size < size)
                    glUsbCtlTxCnt = UsbDescriptorInfo.StrDescriptor4Size;
                break;
            default:
                csr = UsbReadEp0CSR();
                UsbWriteEp0CSR(csr | SET_EP0_SENDSTALL);
                RTNA_DBG_Str(0, "Unsupport StrDESCRIPTOR Type");
                break;
            }
            break;
        default:
            csr = UsbReadEp0CSR();
            UsbWriteEp0CSR(csr | SET_EP0_SENDSTALL);
            RTNA_DBG_Str(0, "Unsupport DESCRIPTOR Type");
            break;
        }
        glUsbCtlState = USB_CONTROL_TX;
        break;

    case STD_GET_STATUS_CMD:
        glUsbCtlTxCnt = 2;
        glUsbCtlState = USB_CONTROL_TX;
        break;

    case STD_CLEAR_FEATURE_CMD:
        break;

    case STD_SET_FEATURE_CMD:
        break;

    case STD_SET_ADDRESS_CMD:
        break;

    case STD_GET_CONFIGURATION_CMD:
        glUsbCtlTxCnt = 1;
        glUsbCtlState = USB_CONTROL_TX;
        break;

    case STD_SET_CONFIGURATION_CMD:
        break;

    case STD_GET_INTERFACE_CMD:
        glUsbCtlTxCnt = 1;
        glUsbCtlState = USB_CONTROL_TX;
        break;

    case STD_SET_INTERFACE_CMD:
        break;

    case STD_SYNCH_FRAME_CMD:
        glUsbCtlTxCnt = 2;
        glUsbCtlState = USB_CONTROL_TX;
        break;

    default:
        csr = UsbReadEp0CSR();
        UsbWriteEp0CSR(csr | SET_EP0_SENDSTALL);
        RTNA_DBG_Str(0, "Unsupport Std Request");
        break;
    }
}
//------------------------------------------------------------------------------
//  Function    : UsbStdCmdNoDataPhase
//  Parameter   : None
//  Return Value : None
//  Description :
//------------------------------------------------------------------------------
void UsbStdCmdNoDataPhase(void)
{
    MMP_UBYTE request,receiver,ep_address;
    MMP_USHORT index,csr,value;

    request = UsbRequestPayload.bRequest;
    receiver = UsbRequestPayload.bmRequestType & USB_REQUEST_RECEIVER_MASK;
    index = UsbRequestPayload.wIndex;
    value = UsbRequestPayload.wValue;

    switch(request) {
    case STD_SET_ADDRESS_CMD:
        glUsbUpdateDeviceAddr = 1;
        break;
    case STD_CLEAR_FEATURE_CMD:
        ep_address = index & USB_ENDPOINT_ADDRESS_MASK;
        switch(receiver) {
        case REQUEST_RECIVER_DEVICE:
            gsUsbDeviceStatus = gsUsbDeviceStatus & CLEAR_WAKEUP_FEATURE;
            break;
        case REQUEST_RECIVER_INTERFACE:
            gsUsbInterfaceStatus[index] = 0;
            break;
        case REQUEST_RECIVER_ENDPOINT:
            if(ep_address == 0) {
                gsUsbEp0Status = gsUsbEp0Status & CLEAR_HALT_FEATURE;
            } else if(index & 0x80) {
                gsUsbTxEpStatus[ep_address] = gsUsbTxEpStatus[ep_address] & CLEAR_HALT_FEATURE;
                csr = UsbReadTxEpCSR(ep_address);
                csr = csr & TXCSR_RW_MASK;
                UsbWriteTxEpCSR(ep_address, (csr & (~TX_SENDSTALL_BIT)) | SET_TX_CLRDATATOG);
            } else {
                gsUsbRxEpStatus[ep_address] = gsUsbRxEpStatus[ep_address] & CLEAR_HALT_FEATURE;
                csr = UsbReadRxEpCSR(ep_address);
                csr = csr & RXCSR_RW_MASK;
                UsbWriteRxEpCSR(ep_address, (csr & (~RX_SENDSTALL_BIT)) | SET_RX_CLRDATATOG);
            }
            break;
        }
        break;

    case STD_SET_CONFIGURATION_CMD:
        glUsbCurrentConfig = UsbRequestPayload.wValue;
        break;
    case STD_SET_FEATURE_CMD:
        if(value == TEST_MODE_FEATURE) {
            RTNA_DBG_Str(0, "TEST_MODE_FEATURE\r\n");

            RTNA_DBG_Short(0, index);
            RTNA_DBG_Str(0, "\r\n");

            glTestModeFeature = index;
        } else {
            ep_address = index & USB_ENDPOINT_ADDRESS_MASK;
            switch(receiver) {
            case REQUEST_RECIVER_DEVICE:
                gsUsbDeviceStatus = gsUsbDeviceStatus | SET_WAKEUP_FEATURE;
                break;
            case REQUEST_RECIVER_INTERFACE:
                gsUsbInterfaceStatus[index] = 0;
                break;
            case REQUEST_RECIVER_ENDPOINT:
                if(ep_address == 0) {
                    gsUsbEp0Status = SET_HALT_FEATURE;
                } else if(index & 0x80) {
                    gsUsbTxEpStatus[ep_address] = SET_HALT_FEATURE;
                } else {
                    gsUsbRxEpStatus[ep_address] = SET_HALT_FEATURE;
                }
                break;
            }
        }
        break;
    case STD_SET_INTERFACE_CMD:
        glUsbCurrentInterface = UsbRequestPayload.wValue;
        break;

    default:
        RTNA_DBG_Str(0, "UsbStdCmdNoDataPhase error\r\n");
        break;
    }
}
//------------------------------------------------------------------------------
//  Function    : UsbStdCmdTx
//  Parameter   : None
//  Return Value : None
//  Description :
//------------------------------------------------------------------------------
void UsbStdCmdTx(void)
{
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;
    MMP_UBYTE request,receiver,ep_address,type;
    MMP_USHORT index,i;


    request = UsbRequestPayload.bRequest;
    receiver = UsbRequestPayload.bmRequestType & USB_REQUEST_RECEIVER_MASK;
    index = UsbRequestPayload.wIndex;

    switch(request) {
    case STD_GET_STATUS_CMD:
        glUsbCtlTxCnt -= 2;
        ep_address = index & USB_ENDPOINT_ADDRESS_MASK;
        switch(receiver) {
        case REQUEST_RECIVER_DEVICE:
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_W = gsUsbDeviceStatus;
            break;

        case REQUEST_RECIVER_INTERFACE:
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_W = gsUsbInterfaceStatus[index];
            break;

        case REQUEST_RECIVER_ENDPOINT:
            if(ep_address == 0)
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_W = gsUsbEp0Status;
            else if(index & 0x80)
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_W = gsUsbTxEpStatus[ep_address];
            else
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_W = gsUsbRxEpStatus[ep_address];
            break;
        }
        break;

    case STD_GET_DESCRIPTOR_CMD:
        type = (UsbRequestPayload.wValue >> 8);
        index = (UsbRequestPayload.wValue & 0xFF);
        switch(type) {
        case DEVICE_DESCRIPTOR:
            for(i = 0;i < glUsbCtlTxCnt;i++) {
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = UsbDescriptorInfo.pDeviceDescriptor[i];
            }
            break;
        case DEVICE_QUALIFIER_DESCRIPTOR:
            for(i = 0;i < glUsbCtlTxCnt;i++) {
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = UsbDescriptorInfo.pDeviceQualifierDescriptor[i];
            }
            break;
                case OTHER_SPEED_CONFIG_DESCRIPTOR:
            for(i = 0;i < glUsbCtlTxCnt;i++) {
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = UsbDescriptorInfo.pOtherSpeedConfigDescriptor[i];
            }
            break;
                case CONFIG_DESCRIPTOR:
            for(i = 0;i < glUsbCtlTxCnt;i++) {
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = UsbDescriptorInfo.pConfigDescriptor[i];
            }
            break;
        case STRING_DESCRIPTOR:
            switch(index) {
            case 0:
                for(i = 0;i < glUsbCtlTxCnt;i++) {
                    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = UsbDescriptorInfo.pStrDescriptor0[i];
                }
                break;
            case 1:
                for(i = 0;i < glUsbCtlTxCnt;i++) {
                    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = UsbDescriptorInfo.pStrDescriptor1[i];
                }
                break;
            case 2:
                for(i = 0;i < glUsbCtlTxCnt;i++) {
                    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = UsbDescriptorInfo.pStrDescriptor2[i];
                }
                break;
            case 3:
                for(i = 0;i < glUsbCtlTxCnt;i++) {
                    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = UsbDescriptorInfo.pStrDescriptor3[i];
                }
                break;
            case 0xEE:
                //Microsoft OS String Descriptor
                RTNA_DBG_Str(0, "Microsoft OS String Descriptor\r\n");
                for(i = 0;i < glUsbCtlTxCnt;i++) {
                    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = UsbDescriptorInfo.pStrDescriptor4[i];
                }
                break;
            }
            break;
        }
        glUsbCtlTxCnt = 0;
        break;

    case STD_GET_CONFIGURATION_CMD:
        glUsbCtlTxCnt -= 1;
        pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = glUsbCurrentConfig;
        break;

    case STD_GET_INTERFACE_CMD:
        glUsbCtlTxCnt -= 1;
        pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = glUsbCurrentInterface;
        break;

    case STD_SYNCH_FRAME_CMD:
        glUsbCtlTxCnt -= 2;
        pUSB_CTL->USB_FIFO_EP[0x0].FIFO_W = 0;
        break;
    default:
        RTNA_DBG_Str(0, "UsbStdCmdTx error\r\n");
        break;
    }
    if(glUsbCtlTxCnt == 0) {
        UsbWriteEp0CSR(SET_EP0_TXPKTRDY | EP0_DATAEND_BIT);
        glUsbCtlState = USB_CONTROL_IDLE;
    } else {
        UsbWriteEp0CSR(SET_EP0_TXPKTRDY);
    }
}
//------------------------------------------------------------------------------
//  Function    : UsbStdCmdRx
//  Parameter   : None
//  Return Value : None
//  Description :
//------------------------------------------------------------------------------
void UsbStdCmdRx(void)
{
}
#endif


#endif  //#if   defined(USB_FW)
//#undef exUSBSTD

/// @}